package com.idea.relax.redis.limiter.client;

import com.idea.relax.redis.limiter.reject.RedisLimiterException;
import com.idea.relax.redis.lock.support.CheckedSupplier;
import com.idea.relax.redis.support.utils.RelaxUtil;

import java.util.concurrent.TimeUnit;

/**
 * @author salad
 */
public interface RedisLimiterClient {

    /**
     * 服务是否被限流
     *
     * @param key    自定义的key，请保证唯一
     * @param count  支持的最大请求
     * @param period 时间,单位默认为秒（seconds）
     * @return 是否允许
     */
    default boolean isAllowed(String key, long count, long period) {
        return this.isAllowed(key, count, period, TimeUnit.SECONDS);
    }

    /**
     * 服务是否被限流
     *
     * @param key      自定义的key，请保证唯一
     * @param count    支持的最大请求
     * @param period   时间
     * @param timeUnit 时间单位
     * @return 是否允许
     */
    boolean isAllowed(String key, long count, long period, TimeUnit timeUnit);

    /**
     * 服务限流，被限制时抛出 RateLimiterException 异常，需要自行处理异常
     *
     * @param key      自定义的key，请保证唯一
     * @param count    支持的最大请求
     * @param period   时间
     * @param timeUnit 时间单位
     * @param supplier Supplier 函数式
     * @param <T>      泛型
     * @return 函数执行结果
     */
    default <T> T allowOrThrow(String key, long count, long period, TimeUnit timeUnit, CheckedSupplier<T> supplier,String errorMessage) {
        boolean isAllowed = this.isAllowed(key, count, period, timeUnit);
        if (isAllowed) {
            try {
                return supplier.get();
            } catch (Throwable e) {
                throw RelaxUtil.unchecked(e);
            }
        }
        throw new RedisLimiterException(errorMessage,key, count, period, timeUnit);
    }

}
